<script setup lang="ts">
import {  onUnmounted, onMounted,ref } from "vue"
import * as mars3d from "mars3d"
import { useMainStore } from '@/store/index'
import { useMainLogin } from '@/store/user'
import { driveTurnto } from "@/utils/help";

// 声明全局window类型
declare global {
  interface Window {
    map: mars3d.Map;
    graphicLayer: mars3d.layer.GraphicLayer;
    graphicDefect: mars3d.layer.GraphicLayer;
    queryLayer: mars3d.layer.queryLayer;
    POISearch: mars3d.layer.GraphicLayer;
    plotting: mars3d.layer.GraphicLayer;
    measurePolygon: mars3d.layer.GraphicLayer;
    measure: mars3d.thing.Measure;
    startEdit: () => void;
  }
}

const Cesium = mars3d.Cesium
const store = useMainStore()
const user = useMainLogin()
const flag = ref(0)

// 用于存放地球组件实例
let map: mars3d.Map // 地图对象

onMounted(()=>{
  initMars3d()
})
const emit = defineEmits(["onload"])

const initMars3d = async () => {
  map = new mars3d.Map(`mars3d-container`,  {
      scene: {
          center:{"lat":33.597926,"lng":120.187673,"alt":165588,"heading":360,"pitch":-90},
          showSkyAtmosphere: false, // 关闭球周边的白色轮廓 map.scene.skyAtmosphere = false
          showSkyBox:false,
          showSun:false,
          showMoon:false,
          globe: {
              showGroundAtmosphere: false, // 关闭大气（球表面白蒙蒙的效果）
              depthTestAgainstTerrain: false,
              baseColor: "#546a53"
          },
          cameraController: {
              zoomFactor: 10.0,
              minimumZoomDistance: 1,
              maximumZoomDistance: 50000000,
              enableTilt:false,
              enableZoom: true
          },
          sceneMode:Cesium.SceneMode.SCENE3D
      },
      basemaps: [{
        name: "天地图影像",
        type: "tdt",
        layer: "img_d",
        key: mars3d.Token.tiandituArr,
        show: true
      },{
        name: "天地图电子",
        type: "tdt",
        layer: "vec_d",
        key: mars3d.Token.tiandituArr,
        show: true,
      },{
        name: "天地图注记(EPSG:4326)",
        type: "tdt",
        show: true,
        zIndex: 99999,
        layer: "img_z",
        key: mars3d.Token.tiandituArr
      }],
      control: {},
      hasTerrain:false
  })

  // 针对不同终端的优化配置
  if (mars3d.Util.isPCBroswer()) {
    // map.zoomFactor = 2.0 // 鼠标滚轮放大的步长参数

    // IE浏览器优化
    if (window.navigator.userAgent.toLowerCase().indexOf("msie") >= 0) {
      map.viewer.targetFrameRate = 60 // 限制帧率
      map.scene.requestRenderMode = true // 取消实时渲染
    }
  } else {
    // map.zoomFactor = 5.0 // 鼠标滚轮放大的步长参数

    // 移动设备上禁掉以下几个选项，可以相对更加流畅
    map.scene.requestRenderMode = true // 取消实时渲染
    map.scene.fog.enabled = false
    map.scene.skyAtmosphere.show = false
    map.scene.globe.showGroundAtmosphere = false
  }

  // //二三维切换不用动画
  if (map.viewer.sceneModePicker) {
    map.viewer.sceneModePicker.viewModel.duration = 0.0
  }

  // webgl渲染失败后，刷新页面
  map.on(mars3d.EventType.renderError, async () => {
    // location.reload()
  })

  emit("onload", map)

  
  mars3d.DrawUtil.setEditPointStyle(mars3d.EditPointType.AddMidPoint, {
    type: mars3d.GraphicType.billboardP,
    image: "https://public-digital-village.obs.cn-north-4.myhuaweicloud.com/c73647eb03168ec7cf4cdc84e779dc7556add03c3698674947b142058d2ff525.png",
    horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
    verticalOrigin: Cesium.VerticalOrigin.CENTER
  });

  window.map = map
  map.unbindContextMenu()
  const distanceLegend = new mars3d.control.DistanceLegend({ right: "80px", bottom: "5vh" })
  map.addControl(distanceLegend)

  window.map.on(mars3d.EventType.wheel, (event) => {
    if (map.getCameraView().alt<=400000 ) {
      if (Math.round(map.getCameraView().alt/1000) >10) {
        map.zoomFactor = 10
      }
      else if(Math.round(map.getCameraView().alt/1000)<3){
        map.zoomFactor = 3
      }
      else{
        map.zoomFactor = Math.round(map.getCameraView().alt/1000)
      }
    }else{
      map.zoomFactor = 10
    }
  })

  // 标绘 点线面图层
  window.graphicLayer = new mars3d.layer.GraphicLayer({
      hasEdit: true,
      isAutoEditing: false, // 绘制完成后是否自动激活编辑
      clustering: {
          enabled: true,
          pixelRange:10,
          clampToGround: false,
      },
  });
  map.addLayer(window.graphicLayer)
  window.graphicLayer.on(mars3d.EventType.editStart, (event) => {
    // 如果有其他编辑状态，先结束它
    if (store.graphicDefectId) {
      window.graphicDefect.stopEditing()
    }
    
    store.closeAllForms()
    store.graphicId = event.graphic._id
    store.graphicOperate = '开始编辑'
    store.saved = true
  })
  window.graphicLayer.on(mars3d.EventType.editStop, (event) => {
    if (!store.isOpenTabel && store.graphicId) {
      store.graphicOperate = '结束修改'
    }
  })
  window.graphicLayer.on(mars3d.EventType.editMovePoint, (event) => {store.saved = false})
  window.graphicLayer.on(mars3d.EventType.click, (event) => {
    if (typeof event.id == 'string') {
    } else {
      // 单击了聚合的点
      const position = event.cartesian
      window.map.flyToPoint(position, {
        radius: 4000, // 距离目标点的距离
      })
    }
  })
  window.graphicLayer.on(mars3d.EventType.drawAddPoint, (event) => {drawFirstPoint(event.cartesian)})
  window.graphicLayer.on(mars3d.EventType.drawRemovePoint, (event) => {delDrawPoint()})
  window.graphicLayer.on(mars3d.EventType.drawCreated, (event) => {endDrawPoint()})

  // 缺陷图层---------------------------------------------------------------------------------
  window.graphicDefect = new mars3d.layer.GraphicLayer({
      hasEdit: true,
      isAutoEditing: false, // 绘制完成后是否自动激活编辑
  });
  map.addLayer(window.graphicDefect)
  // 动态拦截事件（保险措施）
  window.graphicDefect.on(mars3d.EventType.click, (event) => {
    if(!store.isOpenTabel)event.stopPropagation();
  });
  window.graphicDefect.on(mars3d.EventType.editStart, (event) => {
    // 如果有其他编辑状态，先结束它
    if (store.graphicId) {
      window.graphicLayer.stopEditing()
    }
    
    store.isOpenTabel = false
    store.graphicDefectId = event.graphic._id
    store.graphicDefectOperate = '开始编辑'
    store.graphicDefectSaved = true
    window.startEdit()
  })
  window.graphicDefect.on(mars3d.EventType.editStop, (event) => {
    if (!store.isOpenTabel && store.graphicDefectId) {
      store.graphicDefectOperate = '结束修改'
    }
    window.endEdit()
  })
  window.graphicDefect.on(mars3d.EventType.editMovePoint, (event) => {
    store.graphicDefectSaved = false
    console.log('editMovePoint')
    window.resetdefectArea()
  })


  // 搜索图层---------------------------------------------------------------------------------
  window.POISearch = new mars3d.layer.GraphicLayer()
  map.addLayer(window.POISearch)

  // 标绘显示点图层
  window.plotting = new mars3d.layer.GraphicLayer()
  map.addLayer(window.plotting)

  // 测量面积---------------------------------------------------------------------------------
  window.measurePolygon = new mars3d.layer.GraphicLayer({
      hasEdit: true,
      isAutoEditing: true, // 绘制完成后是否自动激活编辑
      clustering: {
          enabled: true,
          pixelRange:10,
      },
  });
  map.addLayer(window.measurePolygon)
  window.measurePolygon.on(mars3d.EventType.editMovePoint, (event) => {
    if(event.editType == "polygon") {
      let graphic = event.graphic
      let area = mars3d.MeasureUtil.getArea(graphic.getCoordinates())
      let areaPF = area.toString().split('.')[0].length>6?(area/1000000).toFixed(2) + ' 平方千米\n ':area.toFixed(2) + ' 平方米\n '
      let areaMu =( area/666.666666667).toFixed(2)
      let text = "面积：" + areaPF + areaMu + " 亩"
      graphic.setStyle({
        label:{
          text:text,
          font_size:16,
          font_family:"微软雅黑",
          outline:true,
          outlineOpacity:1,
          outlineWidth:4
        }
      })
    }
  })

  window.measurePolygon.on(mars3d.EventType.drawAddPoint, (event) => {drawFirstPoint(event.cartesian)})
  window.measurePolygon.on(mars3d.EventType.drawRemovePoint, (event) => {delDrawPoint()})
  window.measurePolygon.on(mars3d.EventType.drawCreated, (event) => {endDrawPoint()})

  // 测量工具---------------------------------------------------------------------------------
  window.measure = new mars3d.thing.Measure({
      label: {
          color: "#ffffff",
          font_family: "楷体",
          font_size: 20,
          background: false
      }
  })
  window.map.addThing(window.measure)
  window.measure.on(mars3d.EventType.drawAddPoint, (event) => {drawFirstPoint(event.cartesian)})
  window.measure.on(mars3d.EventType.drawRemovePoint, (event) => {delDrawPoint()})
  window.measure.on(mars3d.EventType.drawCreated, (event) => {
    endDrawPoint()
    user.isFirst?driveTurnto(5):''
  })

  // 正多边形绘制---------------------------------------------------------------------------------
  window.queryLayer = new mars3d.layer.GraphicLayer({
    hasEdit: true,
    isAutoEditing: false, // 绘制完成后是否自动激活编辑
  });
  map.addLayer(window.queryLayer);
  // 绘制相关变量
  let points = []; // 存储已绘制的经纬度
  let pointEntitys = []; // 存储已绘制的点实例 (Reverted to store Cartesian3 positions)
  let tempPoint; // 存储临时点
  let snappedPosition = null; // 存储吸附点位置
  let isDrawing = false; // 是否正在绘制
  let lines = []; // 存储线段 (Should store graphic objects of lines)
  let lastClickTime = 0; // 记录上次点击时间

  // 开始绘制方法
  window.startDraw = () => {
    isDrawing = true;
    points = [];
    lines.forEach(line => window.queryLayer.removeGraphic(line)); // Clear previous lines
    lines = [];
    if (tempPoint) {
      window.queryLayer.removeGraphic(tempPoint);
      tempPoint = null;
    }
    snappedPosition = null;
    lastClickTime = 0;
  };

  // 撤销上一个点
  window.undoLastPoint = () => {
    console.log('undoLastPoint', pointEntitys)
    if (pointEntitys.length > 0) {
      points.pop()
      const lastPoint = pointEntitys.pop(); // Remove last position
      window.queryLayer.removeGraphic(lastPoint);

      if (lines.length > 0) {
        const lastLine = lines.pop();
        window.queryLayer.removeGraphic(lastLine);
      }

      if (points.length === 0) {
        if (tempPoint) {
          window.queryLayer.removeGraphic(tempPoint);
          tempPoint = null;
        }
      }
    }
  };

  // 结束绘制方法 (Reverted to the version before graphic objects in points array)
  window.endDraw = () => {
    if (points.length >= 3) {
      const lastPoint = points[points.length - 1];
      const prevPoint = points[points.length - 2];
      const firstPoint = points[0];
      
      const lastScreen = map.viewer.scene.cartesianToCanvasCoordinates(lastPoint);
      const prevScreen = map.viewer.scene.cartesianToCanvasCoordinates(prevPoint);
      const firstScreen = map.viewer.scene.cartesianToCanvasCoordinates(firstPoint);
      
      if (lastScreen && prevScreen && firstScreen) {
        const dx = lastScreen.x - prevScreen.x;
        const dy = lastScreen.y - prevScreen.y;
        const baseX = -dy;
        const baseY = dx;
        const APx = firstScreen.x - lastScreen.x;
        const APy = firstScreen.y - lastScreen.y;
        const dot = APx * baseX + APy * baseY;
        const baseSquare = baseX * baseX + baseY * baseY;
        
        if (baseSquare !== 0) {
            const t = dot / baseSquare;
            const snappedScreen = new Cesium.Cartesian2(
              lastScreen.x + t * baseX,
              lastScreen.y + t * baseY
            );
            const ray = map.viewer.camera.getPickRay(snappedScreen);
            if (ray) {
              const snappedCartesian = map.viewer.scene.globe.pick(ray, map.viewer.scene);
              if (snappedCartesian) {
                points.push(snappedCartesian.clone()); // Add position

                // Temporary point for the closing vertex (visual only, not part of final polygon data directly)
                window.queryLayer.addGraphic(new mars3d.graphic.PointEntity({
                  position: snappedCartesian,
                  style: { color: '#00ff00', pixelSize: 12, outlineColor: "#ffffff", outlineWidth: 2 }
                }));

                const lineToClosing = new mars3d.graphic.PolylineEntity({
                    positions: [points[points.length - 2], points[points.length - 1]],
                    style: { color: '#ffffff', width: 2 }
                });
                window.queryLayer.addGraphic(lineToClosing);
                lines.push(lineToClosing);

                const closingLine = new mars3d.graphic.PolylineEntity({
                  positions: [points[points.length - 1], points[0]],
                  style: { color: '#ffffff', width: 2 }
                });
                window.queryLayer.addGraphic(closingLine);
                lines.push(closingLine);
              }
            }
        }
      }
    }
    let pointarr = points
    isDrawing = false;
    points = [];
    pointEntitys = []; // Clear positions array
    lines = []; 
    window.queryLayer.clear()
    if (tempPoint) {
      window.queryLayer.removeGraphic(tempPoint);
      tempPoint = null;
    }
    snappedPosition = null;

    return pointarr
  };

  // 监听鼠标移动事件 (Reverted to use positions from points array)
  map.on(mars3d.EventType.mouseMove, (event) => {
    if (!isDrawing || points.length === 0) return;

    const mousePosition = event.cartesian;
    const lastPointPosition = points[points.length - 1];

    if (points.length === 1) {
      if (!tempPoint) {
        tempPoint = new mars3d.graphic.PointEntity({
          position: mousePosition,
          style: { color: '#ff0000', pixelSize: 10, outlineColor: "#ffffff", outlineWidth: 2 }
        });
        window.queryLayer.addGraphic(tempPoint);
      } else {
        tempPoint.position = mousePosition;
      }
    } else {
      const prevPointPosition = points[points.length - 2];
      const lastScreen = map.viewer.scene.cartesianToCanvasCoordinates(lastPointPosition);
      const prevScreen = map.viewer.scene.cartesianToCanvasCoordinates(prevPointPosition);
      
      if (!lastScreen || !prevScreen) return;
      const dx = lastScreen.x - prevScreen.x;
      const dy = lastScreen.y - prevScreen.y;
      if (Math.sqrt(dx * dx + dy * dy) < 1) {
        if (tempPoint) tempPoint.position = mousePosition;
        snappedPosition = mousePosition.clone(); // Fallback to mouse position if vector is too small
        return;
      }
      const baseX = -dy;
      const baseY = dx;
      const mouseScreen = map.viewer.scene.cartesianToCanvasCoordinates(mousePosition);
      if (!mouseScreen) return;
      const APx = mouseScreen.x - lastScreen.x;
      const APy = mouseScreen.y - lastScreen.y;
      const dot = APx * baseX + APy * baseY;
      const baseSquare = baseX * baseX + baseY * baseY;
      const t = (baseSquare === 0) ? 0 : dot / baseSquare;
      const snappedScreen = new Cesium.Cartesian2(
        lastScreen.x + t * baseX,
        lastScreen.y + t * baseY
      );
      const ray = map.viewer.camera.getPickRay(snappedScreen);
      if (!ray) return;
      const snappedCartesian = map.viewer.scene.globe.pick(ray, map.viewer.scene);
      if (!snappedCartesian) {
        if (tempPoint) tempPoint.position = mousePosition; // Fallback if pick fails
        snappedPosition = mousePosition.clone(); 
        return;
      }
      if (!tempPoint) {
        tempPoint = new mars3d.graphic.PointEntity({
          position: snappedCartesian,
          style: { color: '#ff0000', pixelSize: 10, outlineColor: "#ffffff", outlineWidth: 2 }
        });
        window.queryLayer.addGraphic(tempPoint);
      } else {
        tempPoint.position = snappedCartesian;
      }
      snappedPosition = snappedCartesian.clone();
    }
  });

  // 监听点击事件添加点 (Reverted to store positions in points array)
  map.on(mars3d.EventType.click, (event) => {
    if (!isDrawing) return;

    const currentTime = new Date().getTime();
    const isDoubleClick = currentTime - lastClickTime < 300;
    lastClickTime = currentTime;

    if (event.button === 2) {
      window.undoLastPoint();
      return;
    }

    const positionToAdd = (points.length >= 2 && snappedPosition) ? snappedPosition.clone() : event.cartesian.clone();

    points.push(positionToAdd);
    // Add a temporary visual point for the vertex (these are not the graphics in the `points` array anymore)
    const pointEntity = new mars3d.graphic.PointEntity({
        position: positionToAdd,
        style: { color: '#00ff00', pixelSize: 12, outlineColor: "#ffffff", outlineWidth: 2 }
    });
    window.queryLayer.addGraphic(pointEntity)
    pointEntitys.push(pointEntity); // Store the line graphic

    if (points.length > 1) {
      const line = new mars3d.graphic.PolylineEntity({
        positions: [points[points.length - 2], points[points.length - 1]],
        style: { color: '#ffffff', width: 2 }
      });
      window.queryLayer.addGraphic(line);
      lines.push(line); // Store the line graphic
    }

    if (isDoubleClick && points.length >= 3) {
      window.endDraw();
    }
  });
}

// 新增点标注
const drawFirstPoint = (position) => {
  flag.value ++
  if(window.plotting.length == 0) {
    let point = new mars3d.graphic.PointEntity({
      position:position,
      style:{
        color:"#ff0000"
      }
    })
    point.addTo(window.plotting)
  }
}

const delDrawPoint = () => {
  if(flag.value > 0) {
    flag.value --
  }
  if(flag.value == 0) {
    window.plotting.clear()
  }
}

const endDrawPoint = () => {
  window.plotting.clear()
  flag.value = 0
}

// 组件卸载之前销毁mars3d实例---------------------------------------------------------------------------------
onUnmounted(() => {
  if (map) {
    map.destroy()
    map = null
    location.reload()
  }
})

</script>

<template>
  <div :id="`mars3d-container`" class="mars3d-container">
  </div>
</template>

<style>
.mars3d-container {
  width: 100vw;
  /* height: 105vh; */
  height: 105vh;
  overflow: hidden;
}
.mars3d-locationbar {
  bottom: 5vh !important;
}
.cesium-viewer {
  height: 105vh !important;
}
</style>
